home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJSRC106.ARJ / UNASSMBL.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  28KB  |  1,134 lines

  1. /* This is file UNASSMBL.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* History:255,3 */
  16. #include <stdio.h>
  17. #include <string.h>
  18.  
  19. #include "build.h"
  20. #include "types.h"
  21. #include "gdt.h"
  22. #include "idt.h"
  23. #include "tss.h"
  24. #include "utils.h"
  25. #include "unassmbl.h"
  26. #include "syms.h"
  27. #include "mono.h"
  28.  
  29. #if DEBUGGER
  30.  
  31. int seg_size=32;
  32.  
  33. static word8 buf[20];
  34. static word32 vaddr;
  35. static int bufp, bufe;
  36. static char ubuf[100], *ubufp;
  37. static col;
  38.  
  39. /* Percent tokens in strings:
  40.    First char after '%':
  41.     A - direct address
  42.     C - reg of r/m picks control register
  43.     D - reg of r/m picks debug register
  44.     E - r/m picks operand
  45.     F - flags register
  46.     G - reg of r/m picks general register
  47.     I - immediate data
  48.     J - relative IP offset
  49.     M - r/m picks memory
  50.     O - no r/m, offset only
  51.     R - mod of r/m picks register only
  52.     S - reg of r/m picks segment register
  53.     T - reg of r/m picks test register
  54.     X - DS:ESI
  55.     Y - ES:EDI
  56.     2 - prefix of two-byte opcode
  57.     e - put in 'e' if use32 (second char is part of reg name)
  58.         put in 'w' for use16 or 'd' for use32 (second char is 'w')
  59.     f - floating point (second char is esc value)
  60.     g - do r/m group 'n'
  61.     p - prefix
  62.     s - size override (second char is a,o)
  63.    Second char after '%':
  64.     a - two words in memory (BOUND)
  65.     b - byte
  66.     c - byte or word
  67.     d - dword
  68.     p - 32 or 48 bit pointer
  69.     s - six byte pseudo-descriptor
  70.     v - word or dword
  71.     w - word
  72.     F - use floating regs in mod/rm
  73.     1-8 - group number, esc value, etc
  74. */
  75.  
  76. char *opmap1[] = {
  77. /* 0 */
  78.   "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev",
  79.   "add al,%Ib", "add %eax,%Iv", "push es", "pop es",
  80.   "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev",
  81.   "or al,%Ib", "or %eax,%Iv", "push cs", "%2 ",
  82. /* 1 */
  83.   "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev",
  84.   "adc al,%Ib", "adc %eax,%Iv", "push ss", "pop ss",
  85.   "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev",
  86.   "sbb al,%Ib", "sbb %eax,%Iv", "push ds", "pop ds",
  87. /* 2 */
  88.   "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev",
  89.   "and al,%Ib", "and %eax,%Iv", "%pe", "daa",
  90.   "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev",
  91.   "sub al,%Ib", "sub %eax,%Iv", "%pc", "das",
  92. /* 3 */
  93.   "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev",
  94.   "xor al,%Ib", "xor %eax,%Iv", "%ps", "aaa",
  95.   "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev",
  96.   "cmp al,%Ib", "cmp %eax,%Iv", "%pd", "aas",
  97. /* 4 */
  98.   "inc %eax", "inc %ecx", "inc %edx", "inc %ebx",
  99.   "inc %esp", "inc %ebp", "inc %esi", "inc %edi",
  100.   "dec %eax", "dec %ecx", "dec %edx", "dec %ebx",
  101.   "dec %esp", "dec %ebp", "dec %esi", "dec %edi",
  102. /* 5 */
  103.   "push %eax", "push %ecx", "push %edx", "push %ebx",
  104.   "push %esp", "push %ebp", "push %esi", "push %edi",
  105.   "pop %eax", "pop %ecx", "pop %edx", "pop %ebx",
  106.   "pop %esp", "pop %ebp", "pop %esi", "pop %edi",
  107. /* 6 */
  108.   "pusha", "popa", "bound %Gv,%Ma", "arpl %Ew,%Rw",
  109.   "%pf", "%pg", "%so", "%sa",
  110.   "push %Iv", "imul %Gv=%Ev*%Iv", "push %Ib", "imul %Gv=%Ev*%Ib",
  111.   "insb %Yb,dx", "ins%ew %Yv,dx", "outsb dx,%Xb", "outs%ew dx,%Xv",
  112. /* 7 */
  113.   "jo %Jb", "jno %Jb", "jnc %Jb", "jc %Jb",
  114.   "jz %Jb", "jnz %Jb", "jbe %Jb", "jnbe %Jb",
  115.   "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb",
  116.   "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb",
  117. /* 8 */
  118.   "%g1 %Eb,%Ib", "%g1 %Ev,%Iv", "mov al,%Ib", "%g1 %Ev,%Ib",
  119.   "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv",
  120.   "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev",
  121.   "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev",
  122. /* 9 */
  123.   "nop", "xchg %eax,%ecx", "xchg %eax,%edx", "xchg %eax,%ebx",
  124.   "xchg %eax,%esp", "xchg %eax,%ebp", "xchg %eax,%esi", "xchg %eax,%edi",
  125.   "cbw", "cwd", "call %Ap", "fwait",
  126.   "push %eflags", "pop %eflags", "sahf", "lahf",
  127. /* a */
  128.   "mov al,%Ob", "mov %eax,%Ov", "mov %Ob,al", "mov %Ov,%eax",
  129.   "movsb %Xb,%Yb", "movs%ew %Xv,%Yv", "cmpsb %Xb,%Yb", "cmps%ew %Xv,%Yv",
  130.   "test al,%Ib", "test %eax,%Iv", "stosb %Yb,al", "stos%ew %Yv,%eax",
  131.   "lodsb al,%Xb", "lods%ew %eax,%Xv", "scasb al,%Xb", "scas%ew %eax,%Xv",
  132. /* b */
  133.   "mov al,%Ib", "mov cl,%Ib", "mov dl,%Ib", "mov bl,%Ib",
  134.   "mov ah,%Ib", "mov ch,%Ib", "mov dh,%Ib", "mov bh,%Ib",
  135.   "mov %eax,%Iv", "mov %ecx,%Iv", "mov %edx,%Iv", "mov %ebx,%Iv",
  136.   "mov %esp,%Iv", "mov %ebp,%Iv", "mov %esi,%Iv", "mov %edi,%Iv",
  137. /* c */
  138.   "%g2 %Eb,%Ib", "%g2 %Ev,%Ib", "ret %Iw", "ret",
  139.   "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ib", "mov %Ev,%Iv",
  140.   "enter %Iw,%Ib", "leave", "retf %Iw", "retf",
  141.   "int 3", "int %Ib", "into", "iret",
  142. /* d */
  143.   "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
  144.   "aam", "aad", 0, "xlat",
  145. #if 0
  146.   "esc 0,%Ib", "esc 1,%Ib", "esc 2,%Ib", "esc 3,%Ib",
  147.   "esc 4,%Ib", "esc 5,%Ib", "esc 6,%Ib", "esc 7,%Ib",
  148. #else
  149.   "%f0", "%f1", "%f2", "%f3",
  150.   "%f4", "%f5", "%f6", "%f7",
  151. #endif
  152. /* e */
  153.   "loopne %Jb", "loope %Jb", "loop %Jb", "jcxz %Jb",
  154.   "in al,%Ib", "in %eax,%Ib", "out %Ib,al", "out %Ib,%eax",
  155.   "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Jb",
  156.   "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax",
  157. /* f */
  158.   "lock %p ", 0, "repne %p ", "rep(e) %p ",
  159.   "hlt", "cmc", "%g3", "%g0",
  160.   "clc", "stc", "cli", "sti",
  161.   "cld", "std", "%g4", "%g5"
  162.   };
  163.  
  164. char *second[] = {
  165. /* 0 */
  166.   "%g6", "%g7", "lar %Gv,%Ew", "lsl %Gv,%Ew", 0, 0, "clts", 0,
  167.   0, 0, 0, 0, 0, 0, 0, 0,
  168. /* 1 */
  169.   0, 0, 0, 0, 0, 0, 0, 0,
  170.   0, 0, 0, 0, 0, 0, 0, 0,
  171. /* 2 */
  172.   "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd",
  173.   "mov %Rd,%Td", 0, "mov %Td,%Rd", 0,
  174.   0, 0, 0, 0, 0, 0, 0, 0,
  175. /* 3 */
  176.   0, 0, 0, 0, 0, 0, 0, 0,
  177.   0, 0, 0, 0, 0, 0, 0, 0,
  178.   0, 0, 0, 0, 0, 0, 0, 0,
  179.   0, 0, 0, 0, 0, 0, 0, 0,
  180.   0, 0, 0, 0, 0, 0, 0, 0,
  181.   0, 0, 0, 0, 0, 0, 0, 0,
  182.   0, 0, 0, 0, 0, 0, 0, 0,
  183.   0, 0, 0, 0, 0, 0, 0, 0,
  184.   0, 0, 0, 0, 0, 0, 0, 0,
  185.   0, 0, 0, 0, 0, 0, 0, 0,
  186. /* 8 */
  187.   "jo %Jv", "jno %Jv", "jnc %Jv", "jc %Jv",
  188.   "jz %Jv", "jnz %Jv", "jbe %Jv", "jnbe %Jv",
  189.   "js %Jv", "jns %Jv", "jpe %Jv", "jpo %Jv",
  190.   "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv",
  191. /* 9 */
  192.   "seto %Eb", "setno %Eb", "setnc %Eb", "setc %Eb",
  193.   "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb",
  194.   "sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb",
  195.   "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb",
  196. /* a */
  197.   "push fs", "pop fs", 0, "bt %Ev,%Gv",
  198.   "shld %Ev,%Gv,%Ib", "shld %Ev,%Gv,cl", 0, 0,
  199.   "push gs", "pop gs", 0, "bts %Ev,%Gv",
  200.   "shrd %Ev,%Gv,%Ib", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev",
  201. /* b */
  202.   0, 0, "lss %Mp", "btr %Ev,%Gv",
  203.   "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew",
  204.   0, 0, "%g8 %Ev,%Ib", "btc %Ev,%Gv",
  205.   "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew",
  206. /* c */
  207.   0, 0, 0, 0, 0, 0, 0, 0,
  208.   0, 0, 0, 0, 0, 0, 0, 0,
  209.   0, 0, 0, 0, 0, 0, 0, 0,
  210.   0, 0, 0, 0, 0, 0, 0, 0,
  211.   0, 0, 0, 0, 0, 0, 0, 0,
  212.   0, 0, 0, 0, 0, 0, 0, 0,
  213.   0, 0, 0, 0, 0, 0, 0, 0,
  214.   0, 0, 0, 0, 0, 0, 0, 0,
  215.   };
  216.  
  217. char *groups[][8] = {   /* group 0 is group 3 for %Ev set */
  218.   { "test %Ev,%Iv", "test %Ev,%Iv,", "not %Ev", "neg %Ev",
  219.     "mul %eax,%Ev", "imul %eax,%Ev", "div %eax,%Ev", "idiv %eax,%Ev" },
  220.   { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" },
  221.   { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" },
  222.   { "test %Eb,%Ib", "test %Eb,%Ib,", "not %Eb", "neg %Eb",
  223.     "mul al,%Eb", "imul al,%Eb", "div al,%Eb", "idiv al,%Eb" },
  224.   { "inc %Eb", "dec %Eb", 0, 0, 0, 0, 0, 0 },
  225.   { "inc %Ev", "dec %Ev", "call %Ev", "call %Ep",
  226.     "jmp %Ev", "jmp %Ep", "push %Ev", 0 },
  227.   { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew",
  228.     "verr %Ew", "verw %Ew", 0, 0 },
  229.   { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms",
  230.     "smsw %Ew", 0, "lmsw %Ew", 0 },
  231.   { 0, 0, 0, 0, "bt", "bts", "btr", "btc" }
  232.   };
  233.  
  234. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  235. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  236. char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  237. char *fop_9[]  = { "*fxch st,%GF" };
  238. char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  239. char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  240. char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  241.                    "fldlg2", "fldln2", "fldz", 0 };
  242. char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  243.                    "fxtract", "fprem1", "fdecstp", "fincstp" };
  244. char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  245.                    "frndint", "fscale", "fsin", "fcos" };
  246. char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  247. char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  248. char *fop_32[] = { "*fadd %GF,st" };
  249. char *fop_33[] = { "*fmul %GF,st" };
  250. char *fop_36[] = { "*fsubr %GF,st" };
  251. char *fop_37[] = { "*fsub %GF,st" };
  252. char *fop_38[] = { "*fdivr %GF,st" };
  253. char *fop_39[] = { "*fdiv %GF,st" };
  254. char *fop_40[] = { "*ffree %GF" };
  255. char *fop_42[] = { "*fst %GF" };
  256. char *fop_43[] = { "*fstp %GF" };
  257. char *fop_44[] = { "*fucom %GF" };
  258. char *fop_45[] = { "*fucomp %GF" };
  259. char *fop_48[] = { "*faddp %GF,st" };
  260. char *fop_49[] = { "*fmulp %GF,st" };
  261. char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  262. char *fop_52[] = { "*fsubrp %GF,st" };
  263. char *fop_53[] = { "*fsubp %GF,st" };
  264. char *fop_54[] = { "*fdivrp %GF,st" };
  265. char *fop_55[] = { "*fdivp %GF,st" };
  266. char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  267.  
  268. char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  269.   0, 0, 0, 0, 0, 0, 0, 0,
  270.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  271.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  272.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  273.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  274.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  275.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  276.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  277.   };
  278.  
  279. char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  280. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  281.        "fsub", "fsubr", "fdiv", "fdivr",
  282. /*08*/ "fld", 0, "fst", "fstp",
  283.        "fldenv", "fldcw", "fstenv", "fstcw",
  284. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  285.        "fisub", "fisubr", "fidiv", "fidivr",
  286. /*24*/ "fild", 0, "fist", "fistp",
  287.        "frstor", "fldt", 0, "fstpt",
  288. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  289.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  290. /*40*/ "fldq", 0, "fstq", "fstpq",
  291.        0, 0, "fsave", "fstsww",
  292. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  293.        "fisubw", "fisubrw", "fidivw", "fidivr",
  294. /*56*/ "fildw", 0, "fistw", "fistpw",
  295.        "fbldt", "fildq", "fbstpt", "fistpq"
  296.   };
  297.  
  298. static word8 getbyte()
  299. {
  300.   int s;
  301.   if (bufp >= bufe)
  302.   {
  303.     s = 20;
  304.     if ((vaddr & 0xfff) + s > 0x1000)
  305.       s = 0x1000 - (vaddr & 0xfff);
  306.     memget(vaddr+ARENA, buf, s);
  307.     bufe = s;
  308.     bufp = 0;
  309.   }
  310.   vaddr++;
  311.   printf("%02x", buf[bufp]);
  312.   col+=2;
  313.   return buf[bufp++];
  314. }
  315.  
  316. static prefix;
  317. static modrmv;
  318. static sibv;
  319. static opsize;
  320. static addrsize;
  321.  
  322. static modrm()
  323. {
  324.   if (modrmv == -1)
  325.     modrmv = getbyte();
  326.   return modrmv;
  327. }
  328.  
  329. static sib()
  330. {
  331.   if (sibv == -1)
  332.     sibv = getbyte();
  333.   return sibv;
  334. }
  335.  
  336. #define mod(a)    (((a)>>6)&7)
  337. #define reg(a)    (((a)>>3)&7)
  338. #define rm(a)    ((a)&7)
  339. #define ss(a)    (((a)>>6)&7)
  340. #define indx(a)    (((a)>>3)&7)
  341. #define base(a)    ((a)&7)
  342.  
  343. /*------------------------------------------------------------------------*/
  344. uprintf(char *s, ...)
  345. {
  346.   vsprintf(ubufp, s, ...);
  347.   while (*ubufp) ubufp++;
  348. }
  349.  
  350. uputchar(char c)
  351. {
  352.   if (c == '\t')
  353.   {
  354.     do {
  355.       *ubufp++ = ' ';
  356.     } while ((ubufp-ubuf) % 8);
  357.   }
  358.   else
  359.     *ubufp++ = c;
  360.   *ubufp = 0;
  361. }
  362.  
  363. /*------------------------------------------------------------------------*/
  364. int bytes(char c)
  365. {
  366.   switch (c)
  367.   {
  368.     case 'b':
  369.       return 1;
  370.     case 'w':
  371.       return 2;
  372.     case 'd':
  373.       return 4;
  374.     case 'v':
  375.       if (opsize == 32)
  376.         return 4;
  377.       else
  378.         return 2;
  379.   }
  380.   return 0;
  381. }
  382.  
  383. /*------------------------------------------------------------------------*/
  384. static ohex(char c, int extend, int optional, int defsize, int sign)
  385. {
  386.   int n=0, s=0, i, j;
  387.   int32 delta;
  388.   unsigned char buf[6];
  389.   char *name;
  390.  
  391.   switch (c)
  392.   {
  393.     case 'a':
  394.       break;
  395.     case 'b':
  396.       n = 1;
  397.       break;
  398.     case 'w':
  399.       n = 2;
  400.       break;
  401.     case 'd':
  402.       n = 4;
  403.       break;
  404.     case 's':
  405.       n = 6;
  406.       break;
  407.     case 'c':
  408.     case 'v':
  409.       if (defsize == 32)
  410.         n = 4;
  411.       else
  412.         n = 2;
  413.       break;
  414.     case 'p':
  415.       if (defsize == 32)
  416.         n = 6;
  417.       else
  418.         n = 4;
  419.       s = 1;
  420.       break;
  421.   }
  422.   for (i=0; i<n; i++)
  423.     buf[i] = getbyte();
  424.   for (; i<extend; i++)
  425.     buf[i] = (buf[i-1] & 0x80) ? 0xff : 0;
  426.   if (s)
  427.   {
  428.     uprintf("0x%02x%02x:", buf[n-1], buf[n-2]);
  429.     n -= 2;
  430.   }
  431.   switch (n)
  432.   {
  433.     case 1:
  434.       delta = *(signed char *)buf;
  435.       break;
  436.    case 2:
  437.       delta = *(signed int *)buf;
  438.       break;
  439.     case 4:
  440.       delta = *(signed long *)buf;
  441.       break;
  442.   }
  443.   if (extend > n)
  444.   {
  445.     if (delta || !optional)
  446.       uprintf("%+ld", delta);
  447.     return;
  448.   }
  449.   if ((n == 4) && !sign)
  450.   {
  451.     name = syms_val2name(delta, &delta);
  452.     if (name)
  453.     {
  454.       uprintf("%s", name);
  455.       if (delta)
  456.         uprintf("+%lu", delta);
  457.       return;
  458.     }
  459.   }
  460.   switch (n)
  461.   {
  462.     case 1:
  463.       if (sign)
  464.         uprintf("%+d", (unsigned char)delta);
  465.       else
  466.         uprintf("%#x", (unsigned char)delta);
  467.       break;
  468.     case 2:
  469.       if (sign)
  470.         uprintf("%+d", (unsigned int)delta);
  471.       else
  472.         uprintf("%#x", (unsigned int)delta);
  473.       break;
  474.     case 4:
  475.       if (sign)
  476.         uprintf("%+ld", (unsigned long)delta);
  477.       else
  478.         uprintf("%#lx", (unsigned long)delta);
  479.       break;
  480.   }
  481. }
  482.  
  483. /*------------------------------------------------------------------------*/
  484.  
  485. static char *reg_names[3][8]={
  486.   "al","cl","dl","bl","ah","ch","dh","bh",
  487.   "ax","cx","dx","bx","sp","bp","si","di",
  488.   "eax","ecx","edx","ebx","esp","ebp","esi","edi" };
  489.  
  490. reg_name(int which, char size)
  491. {
  492.   if (size == 'F')
  493.   {
  494.     uprintf("st(%d)", which);
  495.     return;
  496.   }
  497.   if (((size == 'v') && (opsize == 32)) || (size == 'd'))
  498.   {
  499.     uputchar('e');
  500.   }
  501.   if (size == 'b')
  502.   {
  503.     uputchar("acdbacdb"[which]);
  504.     uputchar("llllhhhh"[which]);
  505.   }
  506.   else
  507.   {
  508.     uputchar("acdbsbsd"[which]);
  509.     uputchar("xxxxppii"[which]);
  510.   }
  511. }
  512.  
  513. /*------------------------------------------------------------------------*/
  514. do_sib(m)
  515. {
  516.   int s, i, b;
  517.   s = ss(sib());
  518.   i = indx(sib());
  519.   b = base(sib());
  520.   switch (b)
  521.   {
  522.     case 0: ua_str("%p:[eax"); break;
  523.     case 1: ua_str("%p:[ecx"); break;
  524.     case 2: ua_str("%p:[edx"); break;
  525.     case 3: ua_str("%p:[ebx"); break;
  526.     case 4: ua_str("%p:[esp"); break;
  527.     case 5:
  528.       if (m == 0)
  529.       {
  530.         ua_str("%p:[");
  531.         ohex('d', 4, 0, addrsize, 0);
  532.       }
  533.       else
  534.         ua_str("%p:[ebp");
  535.       break;
  536.     case 6: ua_str("%p:[esi"); break;
  537.     case 7: ua_str("%p:[edi"); break;
  538.   }
  539.   switch (i)
  540.   {
  541.     case 0: uprintf("+eax"); break;
  542.     case 1: uprintf("+ecx"); break;
  543.     case 2: uprintf("+edx"); break;
  544.     case 3: uprintf("+ebx"); break;
  545.     case 4: break;
  546.     case 5: uprintf("+ebp"); break;
  547.     case 6: uprintf("+esi"); break;
  548.     case 7: uprintf("+edi"); break;
  549.   }
  550.   if (i != 4)
  551.     switch (s)
  552.     {
  553.       case 0: uprintf(""); break;
  554.       case 1: uprintf("*2"); break;
  555.       case 2: uprintf("*4"); break;
  556.       case 3: uprintf("*8"); break;
  557.     }
  558. }
  559. /*------------------------------------------------------------------------*/
  560. do_modrm(char t)
  561. {
  562.   int m = mod(modrm());
  563.   int r = rm(modrm());
  564.   int extend = (addrsize == 32) ? 4 : 2;
  565.   if (m == 3)
  566.   {
  567.     reg_name(r, t);
  568.     return;
  569.   }
  570.   if ((m == 0) && (r == 5) && (addrsize == 32))
  571.   {
  572.     ua_str("%p:[");
  573.     ohex('d', extend, 0, addrsize, 0);
  574.     uputchar(']');
  575.     return;
  576.   }
  577.   if ((m == 0) && (r == 6) && (addrsize == 16))
  578.   {
  579.     ua_str("%p:[");
  580.     ohex('w', extend, 0, addrsize, 0);
  581.     uputchar(']');
  582.     return;
  583.   }
  584.   if ((addrsize != 32) || (r != 4))
  585.     ua_str("%p:[");
  586.   if (addrsize == 16)
  587.   {
  588.     switch (r)
  589.     {
  590.       case 0: uprintf("bx+si"); break;
  591.       case 1: uprintf("bx+di"); break;
  592.       case 2: uprintf("bp+si"); break;
  593.       case 3: uprintf("bp+di"); break;
  594.       case 4: uprintf("si"); break;
  595.       case 5: uprintf("di"); break;
  596.       case 6: uprintf("bp"); break;
  597.       case 7: uprintf("bx"); break;
  598.     }
  599.   }
  600.   else
  601.   {
  602.     switch (r)
  603.     {
  604.       case 0: uprintf("eax"); break;
  605.       case 1: uprintf("ecx"); break;
  606.       case 2: uprintf("edx"); break;
  607.       case 3: uprintf("ebx"); break;
  608.       case 4: do_sib(m); break;
  609.       case 5: uprintf("ebp"); break;
  610.       case 6: uprintf("esi"); break;
  611.       case 7: uprintf("edi"); break;
  612.     }
  613.   }
  614.   switch (m)
  615.   {
  616.     case 1:
  617.       ohex('b', extend, 1, addrsize, 0);
  618.       break;
  619.     case 2:
  620.       ohex('v', extend, 1, addrsize, 1);
  621.       break;
  622.   }
  623.   uputchar(']');
  624. }
  625.  
  626. /*------------------------------------------------------------------------*/
  627. static floating_point(int e1)
  628. {
  629.   int esc = e1*8 + reg(modrm());
  630.   if (mod(modrm()) == 3)
  631.   {
  632.     if (fspecial[esc])
  633.     {
  634.       if (fspecial[esc][0][0] == '*')
  635.       {
  636.         ua_str(fspecial[esc][0]+1);
  637.       }
  638.       else
  639.       {
  640.         ua_str(fspecial[esc][rm(modrm())]);
  641.       }
  642.     }
  643.     else
  644.     {
  645.       ua_str(floatops[esc]);
  646.       ua_str(" %EF");
  647.     }
  648.   }
  649.   else
  650.   {
  651.     ua_str(floatops[esc]);
  652.     ua_str(" %EF");
  653.   }
  654. }
  655.  
  656. /*------------------------------------------------------------------------*/
  657. static percent(char c, char t)
  658. {
  659.   word32 vofs, v, delta;
  660.   char *name;
  661.   int extend = (addrsize == 32) ? 4 : 2;
  662.   switch (c)
  663.   {
  664.     case 'A':
  665.       ohex(t, extend, 0, addrsize, 0);
  666.       break;
  667.     case 'C':
  668.       uprintf("cr%d", reg(modrm()));
  669.       break;
  670.     case 'D':
  671.       uprintf("dr%d", reg(modrm()));
  672.       break;
  673.     case 'E':
  674.       do_modrm(t);
  675.       break;
  676.     case 'G':
  677.       if (t == 'F')
  678.         reg_name(rm(modrm()), t);
  679.       else
  680.         reg_name(reg(modrm()), t);
  681.       break;
  682.     case 'I':
  683.       ohex(t, 0, 0, opsize, 0);
  684.       break;
  685.     case 'J':
  686.       switch (bytes(t))
  687.       {
  688.         case 1:
  689.           vofs = (int8)getbyte();
  690.           break;
  691.         case 2:
  692.           vofs = getbyte();
  693.           vofs += getbyte()<<8;
  694.           vofs = (int16)vofs;
  695.           break;
  696.         case 4:
  697.           vofs = (word32)getbyte();
  698.           vofs |= (word32)getbyte() << 8;
  699.           vofs |= (word32)getbyte() << 16;
  700.           vofs |= (word32)getbyte() << 24;
  701.           break;
  702.       }
  703.       name = syms_val2name(vofs+vaddr, &delta);
  704.       uprintf("%s", name);
  705.       if (delta)
  706.         uprintf("+%lu (0x%lx %c)", delta, vofs+vaddr,
  707.                 (vofs & 0x80000000L) ? 0x1e : 0x1f);
  708.       break;
  709.     case 'M':
  710.       do_modrm(t);
  711.       break;
  712.     case 'O':
  713.       ua_str("%p:[");
  714.       ohex(t, extend, 0, addrsize, 0);
  715.       uputchar(']');
  716.       break;
  717.     case 'R':
  718.       do_modrm(t);
  719.       break;
  720.     case 'S':
  721.       uputchar("ecsdfg"[reg(modrm())]);
  722.       uputchar('s');
  723.       break;
  724.     case 'T':
  725.       uprintf("tr%d", reg(modrm()));
  726.       break;
  727.     case 'X':
  728.       uprintf("ds:[");
  729.       if (addrsize == 32)
  730.         uputchar('e');
  731.       uprintf("si]");
  732.       break;
  733.     case 'Y':
  734.       uprintf("es:[");
  735.       if (addrsize == 32)
  736.         uputchar('e');
  737.       uprintf("di]");
  738.       break;
  739.     case '2':
  740.       ua_str(second[getbyte()]);
  741.       break;
  742.     case 'e':
  743.       if (opsize == 32)
  744.       {
  745.         if (t == 'w')
  746.           uputchar('d');
  747.         else
  748.         {
  749.           uputchar('e');
  750.           uputchar(t);
  751.         }
  752.       }
  753.       else
  754.         uputchar(t);
  755.       break;
  756.     case 'f':
  757.       floating_point(t-'0');
  758.       break;
  759.     case 'g':
  760.       ua_str(groups[t-'0'][reg(modrm())]);
  761.       break;
  762.     case 'p':
  763.       switch (t)
  764.       {
  765.         case 'c':
  766.         case 'd':
  767.         case 'e':
  768.         case 'f':
  769.         case 'g':
  770.         case 's':
  771.           prefix = t;
  772.           ua_str(opmap1[getbyte()]);
  773.           break;
  774.         case ':':
  775.           if (prefix)
  776.             uprintf("%cs:", prefix);
  777.           break;
  778.         case ' ':
  779.           ua_str(opmap1[getbyte()]);
  780.           break;
  781.       }
  782.       break;
  783.     case 's':
  784.       switch (t)
  785.       {
  786.         case 'a':
  787.           addrsize = 48 - addrsize;
  788.           ua_str(opmap1[getbyte()]);
  789.           break;
  790.         case 'o':
  791.           opsize = 48 - opsize;
  792.           ua_str(opmap1[getbyte()]);
  793.           break;
  794.       }
  795.       break;
  796.   }
  797. }
  798.  
  799. static ua_str(char *s)
  800. {
  801.   int i, c;
  802.   if (s == 0)
  803.   {
  804.     uprintf("<invalid>");
  805.     return;
  806.   }
  807.   while ((c = *s++) != 0)
  808.   {
  809.     if (c == '%')
  810.     {
  811.       c = *s++;
  812.       percent(c, *s++);
  813.     }
  814.     else
  815.       if (c == ' ')
  816.         uputchar('\t');
  817.       else
  818.         uputchar(c);
  819.   }
  820. }
  821.   
  822. #ifdef SOURCE_LIST
  823. /*
  824. ** A little brute force hacking and hey presto! A source debugger!
  825. ** Courtesy of Kent Williams williams@herky.cs.uiowa.edu
  826. **
  827. ** KNOWN BUGS:
  828. ** The program will summarily terminate if you run out
  829. ** of memory while you're looking for all the line offsets.  Since
  830. ** a two thousand line source file only creats an 8K array, and the
  831. ** symbol table goes into virtual memory, this shouldn't happen too
  832. ** often.
  833. **
  834. ** One file is left open for reading indefinitely.
  835. */
  836. #include <stdlib.h>
  837. #include <string.h>
  838. /*
  839. ** keep the source line offsets in virtual memory, so you can
  840. ** debug big programs
  841. */
  842. extern word32 salloc(word32 size);
  843. extern void symsput(word32 where, void *ptr, int size);
  844. extern void symsget(word32 where, void *ptr, int size);
  845.  
  846. /*
  847. ** for each file encountered, keep an array of line start offsets
  848. ** so you can seek into the file to display the current line.
  849. */
  850. typedef struct {
  851.     char *filename;
  852.     word32 offsets;
  853. } line_info;
  854.  
  855. static line_info files[32];
  856. static last_file = 0;
  857.  
  858. /*
  859. ** these don't seem to be defined anywhere else ...
  860. */
  861. static void *
  862. xmalloc(unsigned size) {
  863.     void *rval = malloc(size);
  864.     if(!rval) {
  865.         fprintf(stderr,"Out of memory\n");
  866.         exit(1);
  867.     }
  868.     return rval;
  869. }
  870.  
  871. static void *
  872. xrealloc(void *rval,unsigned size) {
  873.     rval = realloc(rval,size);
  874.     if(!rval) {
  875.         fprintf(stderr,"Out of memory\n");
  876.         exit(1);
  877.     }
  878.     return rval;
  879. }
  880.  
  881. static char *
  882. xstrdup(char *s) { 
  883.     char *rval = xmalloc(strlen(s)+1);
  884.     strcpy(rval,s);
  885.     return rval;
  886. }
  887.  
  888. /*
  889. ** add_file -- add a file to the source line database
  890. */
  891. static int
  892. add_file(char *name) {
  893.     FILE *f = fopen(name,"r");
  894.     char c;
  895.     long *lines,curpos;
  896.     unsigned curline = 0;
  897.  
  898.     if(!f)
  899.         return -1;
  900.  
  901.     files[last_file].filename = xstrdup(name);
  902.     /*
  903.     ** build an array of line offsets in real memory.
  904.     */
  905.     lines = xmalloc(sizeof(long));
  906.     lines[curline++] = curpos = 0L;
  907.  
  908.     while((c = getc(f)) != EOF) {
  909.         curpos++;
  910.         if(c == '\n') {
  911.             lines = xrealloc(lines,sizeof(long)*(curline+1));
  912.             lines[curline++] = curpos;
  913.         }
  914.     }
  915.     /*
  916.     ** now move the whole array into virtual memory
  917.     */
  918.     files[last_file].offsets = salloc(curline*sizeof(long));
  919.     symsput(files[last_file].offsets,lines,(curline*sizeof(long)));
  920.     /*
  921.     ** don't need the real memory version any more
  922.     */
  923.     free(lines);
  924.  
  925.     fclose(f);
  926.  
  927.     last_file++;
  928.     return 0;
  929. }
  930.  
  931. static line_info *
  932. find_file(char *name) {
  933.     int i;
  934.     for(i = 0; i < last_file; i++)
  935.         if(strcmp(name,files[i].filename) == 0)
  936.             return &files[i];
  937.     if(add_file(name) == -1)
  938.             return NULL;
  939.     return find_file(name);
  940. }
  941.  
  942. /*
  943. ** myfopen -- cache the most recently accessed source file
  944. ** so you aren't constantly reopening a new file
  945. */
  946. static FILE *
  947. myfopen(char *name) {
  948.     static char fname[80] = "";
  949.     static FILE *current = NULL;
  950.     if(current != NULL && strcmp(fname,name) == 0)
  951.             return current;
  952.     if(current != NULL) fclose(current);
  953.     strcpy(fname,name);
  954.     return (current = fopen(name,"r"));
  955. }
  956.  
  957. /*
  958. ** put_source_line -- print the current source line, along with
  959. ** the line # and file name, if necessary.
  960. */
  961. void
  962. put_source_line(int fmt,char *name,int line) {
  963.     line_info *current = find_file(name);
  964.     FILE *cur;
  965.     if(current == NULL) {
  966.     regular:
  967.       if(fmt == 0)
  968.           printf(" (%s#%d):\n", name, line);
  969.       else
  970.           printf("#%d:\n", line);
  971.     } else {
  972.         char buf[70];
  973.         long offset;
  974.         if((cur = myfopen(name)) == NULL)
  975.             goto regular;
  976.         /*
  977.         ** get the symbol out of virtual memory
  978.         */
  979.         symsget(current->offsets+((line - 1) * sizeof(long)),
  980.             &offset,sizeof(long));
  981.         fseek(cur,offset,SEEK_SET);
  982.         /*
  983.         ** truncate line so it fits on screen.
  984.         */
  985.         fgets(buf,sizeof(buf)-2,cur);
  986.         if(strchr(buf,'\n') == NULL)
  987.             strcat(buf,"\n");
  988.         if(fmt == 0)
  989.             printf(" (%s#%d): %s", name, line,buf);
  990.         else
  991.             printf("#%d: %s",line,buf);
  992.     }
  993. }
  994.  
  995. #endif
  996.  
  997.  
  998. int last_unassemble_unconditional;
  999. int last_unassemble_jump;
  1000. int last_unassemble_extra_lines;
  1001.  
  1002. word32 unassemble(word32 v, int showregs)
  1003. {
  1004.   int a,b,n,wi, linenum;
  1005.   char *cmp, *brp;
  1006.   word8 *wp;
  1007.   word32 delta;
  1008.   char *name, *lname;
  1009.  
  1010.   last_unassemble_unconditional = 0;
  1011.   last_unassemble_jump = 0;
  1012.   last_unassemble_extra_lines = 0;
  1013.   name = syms_val2name(v, &delta);
  1014.   if (use_ansi)
  1015.     printf("\033[1;36m");
  1016.   mono_attr = MONO_BOLD;
  1017.   if (!delta && (name[0] != '0'))
  1018.   {
  1019.     printf("%s()", name);
  1020.     lname = syms_val2line(v, &linenum, 1);
  1021.     if (lname)
  1022. #ifndef SOURCE_LIST
  1023.       printf(" (%s#%d):\n", lname, linenum);
  1024. #else
  1025.       put_source_line(0,lname,linenum);
  1026. #endif
  1027.     else
  1028.       printf(":\n");
  1029.     last_unassemble_extra_lines++;
  1030.   }
  1031.   else
  1032.   {
  1033.     lname = syms_val2line(v, &linenum, 1);
  1034.     if (lname)
  1035.     {
  1036. #ifndef SOURCE_LIST
  1037.       printf("#%d:\n", linenum);
  1038. #else
  1039.       put_source_line(1,lname,linenum);
  1040. #endif
  1041.       last_unassemble_extra_lines++;
  1042.     }
  1043.   }
  1044.  
  1045.   if (use_ansi)
  1046.     printf("\033[0m");
  1047.   mono_attr = MONO_NORMAL;
  1048.   printf("%08lx: ", v);
  1049.   if (!page_is_valid(v+ARENA) || !page_is_valid(v+5+ARENA))
  1050.   {
  1051.     printf("<bad address>\n");
  1052.     return v;
  1053.   }
  1054.  
  1055.   prefix = 0;
  1056.   modrmv = sibv = -1;
  1057.   opsize = addrsize = seg_size;
  1058.   vaddr = v;
  1059.   bufp = bufe = 0;
  1060.   col = 0;
  1061.   ubufp = ubuf;
  1062.   ua_str(opmap1[getbyte()]);
  1063.   do {
  1064.     mputchar(' ');
  1065.     col++;
  1066.   } while (col < 15);
  1067.   col += strlen(ubuf);
  1068.   do {
  1069.     uputchar(' ');
  1070.     col++;
  1071.   } while (col < 43);
  1072.   if (use_ansi)
  1073.     printf("\033[1m");
  1074.   mono_attr = MONO_BOLD;
  1075.   printf("%s", ubuf);
  1076.   if (use_ansi)
  1077.     printf("\033[0m");
  1078.   mono_attr = MONO_NORMAL;
  1079.  
  1080.   if ((strncmp(ubuf, "jmp ", 4) == 0)
  1081.      || (strncmp(ubuf, "ret", 3) == 0))
  1082.     last_unassemble_unconditional = 1;
  1083.   if (ubuf[0] == 'j')
  1084.     last_unassemble_jump = 1;
  1085.  
  1086.   if (!showregs)
  1087.   {
  1088.     mputchar('\n');
  1089.     return vaddr;
  1090.   }
  1091.  
  1092.   col -= 43; /* total 25 columns left */
  1093.   wp = (word8 *)&(tss_ptr->tss_eax);
  1094.   cmp = strchr(ubuf+8, ',');
  1095.   brp = strchr(ubuf+8, '[');
  1096.   if (!cmp) cmp = ubuf+8;
  1097.   if (!brp) brp = ubufp;
  1098.   if (brp < cmp) cmp = brp;
  1099.   if (strncmp(ubuf, "mov ", 4))
  1100.     cmp = ubuf+8;
  1101.   for (b=0; b<8; b++)
  1102.   {
  1103.     for (a=2; a>=0; a--)
  1104.     {
  1105.       n = (a==0) ? 1 : ((a==1) ? 2 : 4);
  1106.       if (strstr(cmp, reg_names[a][b]))
  1107.       {
  1108.         col += strlen(reg_names[a][b])+n*2+2;
  1109.         if (col > 29)
  1110.         {
  1111.           printf("\n%53s", "");
  1112.           col = 0;
  1113.         }
  1114.         printf("%s=", reg_names[a][b]);
  1115.         if (a == 0)
  1116.           wi = (b&3)*4 + (b>>2);
  1117.         else
  1118.           wi = b*4;
  1119.         while (n)
  1120.         {
  1121.           n--;
  1122.           printf("%02x", wp[wi+n]);
  1123.         }
  1124.         mputchar(' ');
  1125.         break;
  1126.       }
  1127.     }
  1128.   }
  1129.   mputchar('\n');
  1130.   return vaddr;
  1131. }
  1132.  
  1133. #endif /* DEBUGGER */
  1134.